package com.unlcn.ils.wms.backend.service.inspectApp.impl;

import cn.huiyunche.commons.constant.QiniuConstant;
import cn.huiyunche.commons.exception.BusinessException;
import cn.huiyunche.commons.utils.QiniuUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.unlcn.ils.wms.backend.bo.inspectAppBO.TmsInspectExcpAttachBO;
import com.unlcn.ils.wms.backend.bo.inspectAppBO.TmsInspectExcpBO;
import com.unlcn.ils.wms.backend.bo.inspectAppBO.TmsInspectExcpDetailBO;
import com.unlcn.ils.wms.backend.enums.*;
import com.unlcn.ils.wms.backend.enums.excp.ExcpStatusEnum;
import com.unlcn.ils.wms.backend.service.inspectApp.WmsOutboundInspectExcpService;
import com.unlcn.ils.wms.base.dto.WmsInspectForAppDTO;
import com.unlcn.ils.wms.base.dto.WmsOutboundInspectExcpDTO;
import com.unlcn.ils.wms.base.mapper.inspectApp.*;
import com.unlcn.ils.wms.base.mapper.outbound.WmsOutboundTaskMapper;
import com.unlcn.ils.wms.base.model.inspectApp.*;
import com.unlcn.ils.wms.base.model.outbound.WmsOutboundTask;
import com.unlcn.ils.wms.base.model.outbound.WmsOutboundTaskExample;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 出库异常业务
 */
@Service
public class WmsOutboundInspectExcpServiceImpl implements WmsOutboundInspectExcpService {

    private Logger logger = LoggerFactory.getLogger(WmsOutboundInspectExcpServiceImpl.class);

    @Autowired
    private WmsOutboundExcpExpandMapper wmsOutbounExcpExpandMapper;

    @Autowired
    private WmsOutboundTaskMapper wmsOutboundTaskMapper;

    @Autowired
    private TmsOutboundInspectExcpMapper tmsOutboundInspectExcpMapper;

    @Autowired
    private TmsOutboundExcpAttachsMapper tmsOutboundExcpAttachsMapper;

    @Autowired
    private TmsOutboundComponentMissMapper tmsOutboundComponentMissMapper;

    @Autowired
    private TmsOutboundInspectLogMapper tmsOutboundInspectLogMapper;


    /**
     * 展示区域的九大区域的异常信息
     */
    @Override
    public List<WmsOutboundInspectExcpDTO> getPositionExcpCountByInspectId(Long outboundId, String whCode) {
        logger.info("WmsOutboundInspectExcpServiceImpl.getPositionExcpCountByInspectId param Long:{}", outboundId);
        if (Objects.equals(outboundId, null)) {
            logger.info("WmsOutboundInspectExcpServiceImpl.getPositionExcpCountByInspectId param Long must not be null");
            throw new BusinessException("运单id不能为空!");
        }
        List<WmsOutboundInspectExcpDTO> result_list = null;
        try {
            result_list = new ArrayList<>();
            //获取九大区域
            HashMap<String, Object> params = Maps.newHashMap();
            params.put("notDel", DeleteFlagEnum.NORMAL.getValue());
            params.put("whCode", whCode);
            params.put("parentCode", 0);
            List<WmsOutboundInspectExcpDTO> positionList = wmsOutbounExcpExpandMapper.selectPositionsByInspectId(params);
            if (CollectionUtils.isNotEmpty(positionList)) {
                for (WmsOutboundInspectExcpDTO position : positionList) {
                    //统计异常的数量
                    WmsOutboundInspectExcpDTO result = new WmsOutboundInspectExcpDTO();
                    params.put("positionId", position.getPositionId());
                    params.put("outboundId", outboundId);
                    params.put("closeExcp", TmsInsepectExcpStatusEnum.BILL_CLOSEERROR.getValue());
                    params.put("inspectId",outboundId);
                    int count = wmsOutbounExcpExpandMapper.selectExcpCountByPositionIdAndInspectId(params);
                    result.setPositionId(position.getPositionId());
                    result.setConstantPositionName(position.getConstantPositionName());
                    result.setConstantPositionSort(position.getConstantPositionSort());
                    result.setCountExcp(count);
                    result_list.add(result);
                }
            }
        } catch (Exception e) {
            logger.error("WmsOutboundInspectExcpServiceImpl.getPositionExcpCountByInspectId param Long:{}", e);
            throw new BusinessException("统计区域异常数量异常");
        }
        return result_list;
    }

    /**
     * <p>
     * 2018-5-10 新增仓库code区分
     * </p>
     * 标记异常
     */
    @Override
    public void saveNoteExcp(TmsInspectExcpBO bo) {
        logger.info("WmsOutboundInspectExcpServiceImpl.noteInspectExcp param:{}", bo);
        if (Objects.equals(bo, null)) {
            throw new BusinessException("未发现需要标记的异常");
        }
        Long inspectId = bo.getInspectId();
        String excpDetails = bo.getExcpDetails();
        String userId = bo.getUserId();
        Integer positionId = bo.getPositionId();
        String whCode = bo.getWhCode();
        if (Objects.equals(inspectId, null)) {
            throw new BusinessException("出库单Id不能为空");
        }
        if (Objects.equals(positionId, null)) {
            throw new BusinessException("区域Id不能为空");
        }
        if (StringUtils.isBlank(userId)) {
            throw new BusinessException("用户id不能为空!");
        }
        if (StringUtils.isBlank(whCode)) {
            throw new BusinessException("仓库code不能为空!");
        }

        //判断该验车是否是合格状态,合格状态不能再标记异常
        WmsOutboundTask outboundTask = wmsOutboundTaskMapper.selectByPrimaryKey(inspectId);
        if (!Objects.equals(outboundTask, null)) {
            if (Objects.equals(outboundTask.getInspectStatus(), WmsOutboundInspectStatusEnum.WAYBILL_QUALIFY.getValue())) {
                throw new BusinessException("已发运车辆不能进行异常标记");
            }
            if (Objects.equals(outboundTask.getInspectStatus(), WmsOutboundInspectStatusEnum.WAYBILL_DAMAGE.getValue())) {
                throw new BusinessException("已发运车辆不能进行异常标记");
            }
            //先删除原来的异常和图片
            deleteOldExcpListAndAttaches(bo);

            //2添加对应positionid的异常
            //Gson gson = new Gson();
            //List<TmsInspectExcpDetailBO> detailList = gson.fromJson(excpDetails, new TypeToken<List<TmsInspectExcpDetailBO>>() {
            //}.getType());
            List<TmsInspectExcpDetailBO> detailList = JSONObject.parseArray(excpDetails, TmsInspectExcpDetailBO.class);
            //如果异常信息为空,删除异常
            if (CollectionUtils.isEmpty(detailList)) {
                int excpValue = TmsInsepectExcpStatusEnum.BILL_UNTREATED.getValue();
                int del_flag = DeleteFlagEnum.DELETED.getValue();
                int count1 = wmsOutbounExcpExpandMapper.selectExcpCountByInspectId(inspectId, excpValue, del_flag);
                //统计缺件异常数量
                TmsOutboundComponentMissExample missExample = new TmsOutboundComponentMissExample();
                TmsOutboundComponentMissExample.Criteria criteria = missExample.createCriteria();
                criteria.andInspectIdEqualTo(outboundTask.getOtId())
                        .andIsDeletedNotEqualTo(DeleteFlagEnum.DELETED.getValue());
                int count2 = tmsOutboundComponentMissMapper.countByExample(missExample);
                int count = count1 + count2;
                if (Objects.equals(count, 0)) {
                    //说明都为异常关闭状态,修改验车单为待验车状态
                    modifyInspectStatus(outboundTask, userId, WmsOutboundInspectStatusEnum.WAYBILL_INIT.getValue());
                }
            } else {
                //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
                for (TmsInspectExcpDetailBO excpBO : detailList) {
                    //将异常和验车单关联
                    //先删除原来的异常和图片--因维修要展示经维修并且已关闭的异常为减少判断-在进行异常标注的时候
                    // 1.先将本次要标记的异常在之前的异常记录比对，如果在以前是存在的--就将时间戳及异常类型设置为空(标记异常的时候)
                    //2.插入本次标记的异常及关联的图片
                    //3.再将原来不存在于本次标记异常类的数据并且含有时间戳的数据统一更新为当前要标注的一批的时间戳(验车登记的时候)
                    TmsOutboundInspectExcpExample excpExample = new TmsOutboundInspectExcpExample();
                    excpExample.createCriteria().andInspectIdEqualTo(inspectId)
                            .andConstantBodyCodeEqualTo(excpBO.getConstantBodyCode())
                            .andConstantHurtCodeEqualTo(excpBO.getConstantHurtCode())
                            .andExcpTimestampIsNotNull();
                    TmsOutboundInspectExcp inspectExcp = new TmsOutboundInspectExcp();
                    inspectExcp.setExcpTypeCode(null);
                    inspectExcp.setExcpTimestamp(null);
                    inspectExcp.setGmtUpdate(new Date());
                    tmsOutboundInspectExcpMapper.updateByExampleSelective(inspectExcp, excpExample);

                    excpBO.setPositionId(positionId);
                    TmsOutboundInspectExcp excp = new TmsOutboundInspectExcp();
                    excp.setInspectId(inspectId);
                    excp.setPositionId(positionId);
                    excp.setConstantBodyCode(excpBO.getConstantBodyCode());
                    excp.setConstantHurtCode(excpBO.getConstantHurtCode());
                    excp.setDealStatus(WmsExcpStatusEnum.UNTREATED.getValue());//未处理
                    excp.setDelFlag(true);
                    excp.setGmtCreate(new Date());
                    excp.setGmtUpdate(new Date());
                    excp.setWhCode(whCode);
                    tmsOutboundInspectExcpMapper.insertSelective(excp);
                    //excpIdList.add(excp.getId());
                    // 保存附件
                    String[] attachs = excpBO.getAttachs().split(",");
                    if (!Objects.equals(attachs, null)) {
                        Arrays.stream(attachs).forEach(v -> {
                            TmsOutboundExcpAttachs attach = new TmsOutboundExcpAttachs();
                            attach.setPicKey(v);
                            attach.setExcpId(excp.getId());
                            attach.setGmtCreate(new Date());
                            attach.setGmtUpdate(new Date());
                            tmsOutboundExcpAttachsMapper.insertSelective(attach);
                        });
                    }
                }
                modifyInspectStatus(outboundTask, userId, WmsOutboundInspectStatusEnum.WAYBILL_EXCP.getValue());
            }
            new Thread(() -> {
                //写入日志
                TmsOutboundInspectLog log = new TmsOutboundInspectLog();
                saveLog(bo, log);
                tmsOutboundInspectLogMapper.insertSelective(log);
            }).start();

        }
    }

    /**
     * 展示区域下的异常信息
     */
    @Override
    public List<TmsInspectExcpDetailBO> getInspectExcpListByPositionId(TmsInspectExcpBO bo) {
        logger.info("WmsOutboundInspectExcpServiceImpl.getInspectExcpListByPositionId param:{}", bo);
        if (bo == null) {
            throw new BusinessException("传入参数不能为空!");
        }
        Long inspectId = bo.getInspectId();
        String whCode = bo.getWhCode();
        Integer positionId = bo.getPositionId();
        if (Objects.equals(inspectId, null)) {
            throw new BusinessException("验车单id不能为空!");
        }
        if (Objects.equals(positionId, null)) {
            throw new BusinessException("异常位置id不能为空!");
        }
        if (StringUtils.isBlank(whCode)) {
            throw new BusinessException("仓库code不能为空!");
        }

        //获取对应区域异常列表
        List<TmsInspectExcpDetailBO> result_list = new ArrayList<>();
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("inspectId", inspectId);
        params.put("positionId", positionId);
        params.put("notDel", DeleteFlagEnum.NORMAL.getValue());
        params.put("closeValue", ExcpStatusEnum.CLOSED.getCode());
        params.put("whCode", whCode);
        List<WmsOutboundInspectExcpDTO> excpDTOList = wmsOutbounExcpExpandMapper.selectExcpListByPositionId(params);
        if (CollectionUtils.isNotEmpty(excpDTOList)) {
            for (WmsOutboundInspectExcpDTO dto : excpDTOList) {
                //转换对象
                TmsInspectExcpDetailBO detailBO = new TmsInspectExcpDetailBO();
                BeanUtils.copyProperties(dto, detailBO);
                //获取图片的地址
                TmsOutboundExcpAttachsExample attachsExample = new TmsOutboundExcpAttachsExample();
                TmsOutboundExcpAttachsExample.Criteria criteria = attachsExample.createCriteria();
                criteria.andExcpIdEqualTo(dto.getExcpId());
                criteria.andDelFlagNotEqualTo(false);
                List<TmsOutboundExcpAttachs> attachsList = tmsOutboundExcpAttachsMapper.selectByExample(attachsExample);
                if (CollectionUtils.isNotEmpty(attachsList)) {
                    List<TmsInspectExcpAttachBO> attachBOList = new ArrayList<>();
                    for (TmsOutboundExcpAttachs attachs : attachsList) {
                        TmsInspectExcpAttachBO attachBO = new TmsInspectExcpAttachBO();
                        attachBO.setPicUrl(QiniuUtil.generateDownloadURL(QiniuConstant.QINIU_DOWNLOAD_ADDRESS, attachs.getPicKey(), "", null, null));
                        attachBO.setPicKey(attachs.getPicKey());
                        attachBO.setId(attachs.getId());
                        attachBOList.add(attachBO);
                    }
                    detailBO.setAttachBOS(attachBOList);
                }
                result_list.add(detailBO);
            }
        }
        return result_list;
    }


    /**
     * <p>
     * 2018-5-11 新增接口:一键删除所有异常 验车登记前可以删除 验车登记后需要走维修流程
     * </p>
     *
     * @param dto 参数封装
     */
    @Override
    public void deleteAllException(WmsInspectForAppDTO dto) {
        if (logger.isInfoEnabled()) {
            logger.info("WmsOutboundInspectExcpServiceImpl.deleteAllException param:{}", dto);
        }
        if (dto == null) {
            throw new BusinessException("参数不能为空!");
        }
        Long inspectId = dto.getInspectId();
        String whCode = dto.getWhCode();
        String userId = dto.getUserId();
        if (inspectId == null) {
            throw new BusinessException("单据id不能为空!");
        }
        if (StringUtils.isBlank(whCode)) {
            throw new BusinessException("仓库code不能为空!");
        }
        if (StringUtils.isBlank(userId)) {
            throw new BusinessException("用户id不能为空!");
        }
        //查询订单信息
        WmsOutboundTaskExample example = new WmsOutboundTaskExample();
        example.createCriteria()
                .andOtIdEqualTo(inspectId)
                .andIsDeletedEqualTo(DeleteFlagEnum.NORMAL.getValue());
        List<WmsOutboundTask> tasks = wmsOutboundTaskMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(tasks)) {
            throw new BusinessException("未查询到对应的出库信息");
        }
        WmsOutboundTask task = tasks.get(0);
        int excpValue = TmsInspectStatusEnum.WAYBILL_EXCP.getValue();
        if (!(excpValue == task.getInspectStatus())) {
            throw new BusinessException("只能支持异常状态进行该操作!");
        }
        //删除异常信息--
        HashMap<String, Object> params = Maps.newHashMap();
        params.put("inspectId", inspectId);
        params.put("del", DeleteFlagEnum.DELETED.getValue());
        params.put("whCode", whCode);
        params.put("userId", userId);
        params.put("initValue", TmsInspectStatusEnum.WAYBILL_INIT.getValue());
        //一键删除异常信息 将入库单验车状态改为(待验车)
        wmsOutbounExcpExpandMapper.updateExceptionToDeleteByInspectId(params);
    }

    private void saveLog(TmsInspectExcpBO bo, TmsOutboundInspectLog log) {
        log.setMsg("标记异常成功!");
        log.setUserId(bo.getUserId());
        log.setInspectId(bo.getInspectId());
        log.setGmtUpdate(new Date());
        log.setGmtCreate(new Date());
    }


    /**
     * 修改验车单状态
     */
    private void modifyInspectStatus(WmsOutboundTask outboundTask, String userId, int value) {
        logger.info("WmsOutboundInspectExcpServiceImpl.modifyInspectStatus param :{},{},{}", outboundTask, userId, value);
        try {
            WmsCheckResultEnum resultEnum = WmsCheckResultEnum.getByValue(value);
            if (resultEnum != null) {
                outboundTask.setOtCheckResult(resultEnum.getText());
            }
            WmsCheckDescEnum descEnum = WmsCheckDescEnum.getByValue(value);
            if (descEnum != null) {
                outboundTask.setOtCheckDesc(descEnum.getText());
            }
            outboundTask.setInspectStatus(value);
            outboundTask.setGmtModify(new Date());
            outboundTask.setModifyUserId(userId);
            outboundTask.setInspectTime(new Date());
            wmsOutboundTaskMapper.updateByPrimaryKeySelective(outboundTask);
        } catch (Exception e) {
            logger.error("WmsOutboundInspectExcpServiceImpl.modifyInspectStatus param :{},{},{}", outboundTask, userId, value);
            throw new BusinessException("修改验车单状态异常!");
        }
    }


    /**
     * 删除原来的数据
     */
    private void deleteOldExcpListAndAttaches(TmsInspectExcpBO bo) {
        //1先根据positionId查询删除原来数据库的数据
        TmsOutboundInspectExcpExample outboundInspectExcpExample = new TmsOutboundInspectExcpExample();
        TmsOutboundInspectExcpExample.Criteria criteria = outboundInspectExcpExample.createCriteria();
        criteria.andInspectIdEqualTo(bo.getInspectId());
        criteria.andPositionIdEqualTo(bo.getPositionId());
        criteria.andDelFlagNotEqualTo(false);
        List<TmsOutboundInspectExcp> outboundInspectExcpList = tmsOutboundInspectExcpMapper.selectByExample(outboundInspectExcpExample);
        if (CollectionUtils.isNotEmpty(outboundInspectExcpList)) {
            for (TmsOutboundInspectExcp inspectExcp : outboundInspectExcpList) {
                inspectExcp.setDelFlag(false);//逻辑删除
                inspectExcp.setGmtUpdate(new Date());
                tmsOutboundInspectExcpMapper.updateByPrimaryKeySelective(inspectExcp);
                //逻辑删除数据库中的图片
                TmsOutboundExcpAttachsExample attachsExample = new TmsOutboundExcpAttachsExample();
                TmsOutboundExcpAttachsExample.Criteria attachsExampleCriteria = attachsExample.createCriteria();
                attachsExampleCriteria.andExcpIdEqualTo(inspectExcp.getId());
                attachsExampleCriteria.andDelFlagNotEqualTo(false);
                List<TmsOutboundExcpAttachs> attachsList = tmsOutboundExcpAttachsMapper.selectByExample(attachsExample);
                if (CollectionUtils.isNotEmpty(attachsList)) {
                    for (TmsOutboundExcpAttachs attachs : attachsList) {
                        attachs.setDelFlag(false);//逻辑删除
                        attachs.setGmtUpdate(new Date());
                        tmsOutboundExcpAttachsMapper.updateByPrimaryKeySelective(attachs);
                    }
                }

            }
        }

    }
}
